import { getToken, isValidToken, setToken } from "./auth";
import { ElMessage } from "element-plus";
import router from "@/router";

/**
 * FetchClient - 一个类似axios的fetch封装
 * 支持拦截器、默认配置、自动刷新token等功能
 */
class FetchClient {
  constructor(config = {}) {
    this.baseURL = config.baseURL || process.env.VUE_APP_API_URL || "";
    this.timeout = config.timeout || 15000;
    this.headers = {
      "Content-Type": "application/json",
      ...config.headers,
    };

    // 拦截器
    this.interceptors = {
      request: [],
      response: [],
    };

    // 配置项
    this.config = config;
  }

  /**
   * 添加请求拦截器
   * @param {Function} onFulfilled - 成功回调
   * @param {Function} onRejected - 失败回调
   * @returns {Function} 移除拦截器的方法
   */
  addRequestInterceptor(onFulfilled, onRejected) {
    const interceptor = { onFulfilled, onRejected };
    this.interceptors.request.push(interceptor);

    return () => {
      const index = this.interceptors.request.indexOf(interceptor);
      if (index !== -1) {
        this.interceptors.request.splice(index, 1);
      }
    };
  }

  /**
   * 添加响应拦截器
   * @param {Function} onFulfilled - 成功回调
   * @param {Function} onRejected - 失败回调
   * @returns {Function} 移除拦截器的方法
   */
  addResponseInterceptor(onFulfilled, onRejected) {
    const interceptor = { onFulfilled, onRejected };
    this.interceptors.response.push(interceptor);

    return () => {
      const index = this.interceptors.response.indexOf(interceptor);
      if (index !== -1) {
        this.interceptors.response.splice(index, 1);
      }
    };
  }

  /**
   * 执行所有请求拦截器
   * @param {Object} options - 请求配置
   * @returns {Object} 处理后的请求配置
   */
  async runRequestInterceptors(options) {
    let config = { ...options };

    for (const interceptor of this.interceptors.request) {
      try {
        const result = await interceptor.onFulfilled(config);
        if (result) {
          config = result;
        }
      } catch (error) {
        if (interceptor.onRejected) {
          interceptor.onRejected(error);
        }
        throw error;
      }
    }

    return config;
  }

  /**
   * 执行所有响应拦截器
   * @param {Response} response - Fetch响应对象
   * @param {Object} options - 请求配置
   * @returns {any} 处理后的响应结果
   */
  async runResponseInterceptors(response, options) {
    let result = response;

    // 如果是流，则直接返回
    if (options.responseType === "stream") {
      return result;
    }

    // 非流响应处理为JSON
    let data = null;
    if (response.status !== 204) {
      if (response.headers.get("Content-Type")?.includes("application/json")) {
        data = await response.json();
      } else {
        data = await response.text();
      }
    }

    // 执行响应拦截器
    for (const interceptor of this.interceptors.response) {
      try {
        if (interceptor.onFulfilled) {
          const interceptorResult = await interceptor.onFulfilled(data, response, options);
          if (interceptorResult !== undefined) {
            result = interceptorResult;
          }
        }
      } catch (error) {
        if (interceptor.onRejected) {
          const interceptorResult = await interceptor.onRejected(error, response, options);
          if (interceptorResult !== undefined) {
            return interceptorResult;
          }
        }
        throw error;
      }
    }

    return result;
  }

  /**
   * 处理请求超时
   * @param {Promise} fetchPromise - fetch请求Promise
   * @param {number} timeout - 超时时间(ms)
   * @returns {Promise} 带超时处理的Promise
   */
  timeoutPromise(fetchPromise, timeout) {
    return Promise.race([
      fetchPromise,
      new Promise((_, reject) => {
        setTimeout(() => {
          reject(new Error(`Request timeout after ${timeout}ms`));
        }, timeout);
      }),
    ]);
  }

  /**
   * 发送请求
   * @param {Object} options - 请求配置
   * @returns {Promise} 请求结果
   */
  async request(options) {
    // 合并默认配置
    const requestOptions = {
      method: "GET",
      headers: { ...this.headers },
      ...options,
      url: options.url || "",
    };

    // 执行请求拦截器
    let config = await this.runRequestInterceptors(requestOptions);

    // 构建URL
    let url = config.url;
    if (!url.startsWith("http") && !url.startsWith("//")) {
      url = `${this.baseURL}${url.startsWith("/") ? url : `/${url}`}`;
    }

    // 处理查询参数
    if (config.params) {
      const queryParams = new URLSearchParams();
      Object.entries(config.params).forEach(([key, value]) => {
        if (value !== undefined && value !== null) {
          queryParams.append(key, value);
        }
      });

      const queryString = queryParams.toString();
      if (queryString) {
        url += (url.includes("?") ? "&" : "?") + queryString;
      }
    }

    // 处理请求体
    let body = config.data;
    if (
      body &&
      typeof body === "object" &&
      !(body instanceof FormData) &&
      config.headers["Content-Type"] === "application/json"
    ) {
      body = JSON.stringify(body);
    }

    // 构建fetch选项
    const fetchOptions = {
      method: config.method.toUpperCase(),
      headers: config.headers,
      credentials: config.withCredentials ? "include" : "same-origin",
      redirect: "follow",
      signal: config.signal,
    };

    if (body && config.method.toUpperCase() !== "GET") {
      fetchOptions.body = body;
    }

    try {
      // 发送请求
      let fetchPromise = fetch(url, fetchOptions);

      // 处理超时
      if (config.timeout || this.timeout) {
        fetchPromise = this.timeoutPromise(fetchPromise, config.timeout || this.timeout);
      }

      const response = await fetchPromise;

      // 如果是流式响应，直接返回响应对象
      if (config.responseType === "stream") {
        return response;
      }

      // 执行响应拦截器
      return this.runResponseInterceptors(response, config);
    } catch (error) {
      // 请求错误处理
      for (const interceptor of this.interceptors.response) {
        if (interceptor.onRejected) {
          try {
            const result = await interceptor.onRejected(error);
            if (result !== undefined) {
              return result;
            }
          } catch (interceptorError) {
            error = interceptorError;
          }
        }
      }
      throw error;
    }
  }

  /**
   * GET请求
   * @param {string} url - 请求地址
   * @param {Object} options - 请求配置
   * @returns {Promise} 请求结果
   */
  get(url, options = {}) {
    return this.request({
      method: "GET",
      url,
      ...options,
    });
  }

  /**
   * POST请求
   * @param {string} url - 请求地址
   * @param {any} data - 请求数据
   * @param {Object} options - 请求配置
   * @returns {Promise} 请求结果
   */
  post(url, data, options = {}) {
    return this.request({
      method: "POST",
      url,
      data,
      ...options,
    });
  }

  /**
   * PUT请求
   * @param {string} url - 请求地址
   * @param {any} data - 请求数据
   * @param {Object} options - 请求配置
   * @returns {Promise} 请求结果
   */
  put(url, data, options = {}) {
    return this.request({
      method: "PUT",
      url,
      data,
      ...options,
    });
  }

  /**
   * DELETE请求
   * @param {string} url - 请求地址
   * @param {Object} options - 请求配置
   * @returns {Promise} 请求结果
   */
  delete(url, options = {}) {
    return this.request({
      method: "DELETE",
      url,
      ...options,
    });
  }

  /**
   * PATCH请求
   * @param {string} url - 请求地址
   * @param {any} data - 请求数据
   * @param {Object} options - 请求配置
   * @returns {Promise} 请求结果
   */
  patch(url, data, options = {}) {
    return this.request({
      method: "PATCH",
      url,
      data,
      ...options,
    });
  }
}

// 创建默认实例
const fetchClient = new FetchClient({
  baseURL: process.env.VUE_APP_API_URL,
  timeout: 100000, // 请求超时时间，单位为毫秒
});

// Token刷新相关
let isRefreshing = false;
let refreshSubscribers = [];

const subscribeTokenRefresh = (callback) => {
  refreshSubscribers.push(callback);
};

const onTokenRefreshed = (token) => {
  refreshSubscribers.forEach((callback) => callback(token));
  refreshSubscribers = [];
};

const refreshToken = async () => {
  try {
    const response = await fetch("/api/auth/refreshToken", {
      method: "POST",
      headers: {
        "Content-Type": "application/json",
      },
      credentials: "include",
    });

    if (!response.ok) {
      throw new Error("Failed to refresh token");
    }

    const data = await response.json();
    if (data.success) {
      setToken(data.data);
      return data.data;
    }
    return null;
  } catch (error) {
    console.error("Token refresh failed:", error);
    return null;
  }
};

// 添加请求拦截器
fetchClient.addRequestInterceptor(async (config) => {
  // 添加token
  const token = getToken();
  if (token) {
    if (!isValidToken(token) && !config.url.includes("/auth/")) {
      if (!isRefreshing) {
        isRefreshing = true;
        const newToken = await refreshToken();
        isRefreshing = false;

        if (newToken) {
          onTokenRefreshed(newToken);
          config.headers["Authorization"] = `Bearer ${newToken}`;
          return config;
        }

        try {
          const userStore = window?.$pinia?.state.value?.user;
          if (userStore && userStore.logout) {
            userStore.logout();
          }
        } catch (e) {
          console.error("Failed to logout user:", e);
        }
        router.push("/login");
        return Promise.reject(new Error("登录已过期"));
      }

      return new Promise((resolve) => {
        subscribeTokenRefresh((token) => {
          config.headers["Authorization"] = `Bearer ${token}`;
          resolve(config);
        });
      });
    }

    config.headers["Authorization"] = `Bearer ${token}`;
  }

  return config;
});

// 添加响应拦截器
fetchClient.addResponseInterceptor(
  async (data, response) => {
    // 如果是二进制流，直接返回响应对象
    if (response.headers.get("Content-Type")?.includes("application/octet-stream")) {
      return response;
    }

    // 处理JSON响应
    if (data && data.success === false) {
      ElMessage.error(data.message || "请求失败");

      if (data.status === "401") {
        const newToken = await refreshToken();
        if (newToken) {
          return fetchClient.request(response.config);
        }

        try {
          const userStore = window?.$pinia?.state.value?.user;
          if (userStore && userStore.logout) {
            userStore.logout();
          }
        } catch (e) {
          console.error("Failed to logout user:", e);
        }
        router.push("/login");
      }
    }

    return data;
  },
  async (error) => {
    // 请求出错
    let errorMsg = "网络请求失败";

    if (error.name === "AbortError") {
      errorMsg = "请求已取消";
    } else if (error.message.includes("timeout")) {
      errorMsg = "请求超时";
    } else if (error.response) {
      const { status } = error.response;
      if (status === 401) {
        errorMsg = "登录已过期";
      } else if (status === 403) {
        errorMsg = "权限验证失败，请联系管理员!";
      } else if (status === 404) {
        errorMsg = "请求的资源不存在";
      } else if (status >= 500) {
        errorMsg = "服务器内部错误";
      }
    }

    ElMessage.error(errorMsg);

    return {
      success: false,
      message: errorMsg,
      errorCode: error.response?.status || "NETWORK_ERROR",
      data: null,
    };
  }
);

export default fetchClient;
